#include <stdio.h>
#include <stdlib.h>
#include "minilzo.h"

#include "lua.h"
#include "lauxlib.h"

#define BUFF_LEN      (128*1024ul)

/* Work-memory needed for compression. Allocate memory in units
 * of 'lzo_align_t' (instead of 'char') to make sure it is properly aligned.
 */

#define HEAP_ALLOC(var,size) \
    lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ]

static HEAP_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS);

static int 
lcompress(lua_State *L){
	const  char *str;
	unsigned char buff[BUFF_LEN];
	size_t len;
	lzo_uint buff_len;
	str = luaL_checklstring(L, 1, &len);
	if (str == NULL){
		return luaL_argerror(L, 1, "Need a string");
	}
	int r = lzo1x_1_compress((const unsigned char *)str, (lzo_uint)len, buff, &buff_len,wrkmem);
	if (r == LZO_E_OK){
		lua_pushlstring(L, (const char *)buff, buff_len);
		return 1;
	}else{
		return luaL_argerror(L, 1, "r erro");
	}

}

static int
luncompress(lua_State *L){
	const  char *str;
	unsigned char buff[BUFF_LEN];
	size_t len;
	lzo_uint buff_len;
	str = luaL_checklstring(L, 1, &len);
	if (str == NULL){
		return luaL_argerror(L, 1, "Need a string");
	}
	int r = lzo1x_decompress((const unsigned char *)str, (lzo_uint)len, buff, &buff_len, NULL);
	if (r == LZO_E_OK){
		lua_pushlstring(L, (const char *)buff, buff_len);
		return 1;
	}else{
		return luaL_argerror(L, 1, "r erro");
	}
}

int 
luaopen_lzo(lua_State *L){	
	if (lzo_init() != LZO_E_OK)
    {
        printf("internal error - lzo_init() failed !!!\n");
        printf("(this usually indicates a compiler bug - try recompiling\nwithout optimizations, and enable '-DLZO_DEBUG' for diagnostics)\n");
        return 0;
    }
	luaL_Reg l[] = {
		{ "compress", lcompress },
		{ "uncompress", luncompress },
	
		{ NULL, NULL },
	};
	luaL_newlib(L,l);

	return 1;

}